package com.dragon.logical.service.finance.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.model.ResultCode;
import com.dragon.common.model.exception.CustomException;
import com.dragon.common.util.DateNumUtils;
import com.dragon.logical.service.finance.IBillService;
import com.dragon.logical.service.finance.ICustomerPaymentService;
import com.dragon.logical.service.finance.IPlanCollectService;
import com.dragon.repository.entity.*;
import com.dragon.repository.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * <p>
 * 计划回款表 服务实现类
 * </p>
 *
 * @author sy
 * @since 2023-06-30
 */
@Service
public class PlanCollectServiceImpl extends ServiceImpl<PlanCollectMapper, PlanCollect> implements IPlanCollectService {

    @Autowired
    PlanCollectMapper pcMapper;
    @Autowired
    ContractMapper contractMapper;
    @Autowired
    ProduceMapper produceMapper;
    @Autowired
    QuotesProductsMapper quotesProductsMapper;
    @Autowired
    AdminDepartmentMapper adminDepartmentMapper;
    @Autowired
    ProduceProductsMapper produceProductsMapper;
    @Autowired
    CustomerPaymentMapper customerPaymentMapper;
    @Autowired
    PaymentMapper paymentMapper;
    @Autowired
    LoanMapper loanMapper;
    @Autowired
    ReimbursementMapper reimbursementMapper;
    @Autowired
    PaymentContractMapper paymentContractMapper;
    @Autowired
    BillMapper billMapper;
    @Autowired
    CustomerMapper customerMapper;
    @Autowired
    ICustomerPaymentService customerPaymentService;
    @Autowired
    IPlanCollectService planCollectService;
    @Autowired
    IBillService billService;


    @Override
    public Page<PlanCollect> planList(Integer page, Integer limit, String search, Integer customerId, Integer planStatus, String startTime, String endTime) {
        Page<PlanCollect> planPage = new Page<>(page, limit);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        QueryWrapper<PlanCollect> wrapper = new QueryWrapper<>();
        if (StrUtil.isNotEmpty(startTime) || StrUtil.isNotEmpty(endTime)) {
            if (StrUtil.isEmpty(endTime)) {
                endTime = DateUtil.date().toString();
            }
            if (StrUtil.isEmpty(startTime)) {
                startTime = "1999-01-01";
            }
            try {
                df.parse(startTime);
                df.parse(endTime);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
        }
        wrapper.like(StrUtil.isNotBlank(search),"M.customerName" ,search)
                .eq(customerId != null,"M.customer_id",customerId)
                .eq(planStatus!=null,"M.plan_status",planStatus)
                //.eq("M.bill_status",0)
                .eq("M.bill_status", 0)
                .ge(StrUtil.isNotBlank(startTime), "M.order_time", startTime)
                .le(StrUtil.isNotBlank(endTime), "M.order_time", endTime)
                .orderByDesc("M.create_time");
        Page<PlanCollect> planCollectPage = pcMapper.planList(planPage, wrapper);
        return planCollectPage;
    }

    @Override
    public Integer addPlan(PlanCollect plan) {
        PlanCollect planCollect = pcMapper.selectById(plan.getId());
        if (planCollect != null){
            throw new CustomException(ResultCode.DATA_ALREADY_EXISTS);
        }
        plan.setCreateTime(DateUtil.date());
        pcMapper.insert(plan);
        return plan.getId();
    }

    @Override
    public void updatePlan(PlanCollect plan) {
        if (pcMapper.selectById(plan.getId()) == null){
            throw new CustomException(ResultCode.DATA_NOT_FOUND);
        }
        plan.setUpdateTime(DateUtil.date());
        pcMapper.updateById(plan);
    }

    @Override
    public void deletePlan(Integer id){
        pcMapper.deleteById(id);
    }

    @Override
    public List<PlanCollect> selectByContractId(Integer contractId) {
        return pcMapper.selectListByContractId(contractId);
    }

    @Override
    public PlanCollect selectByPlId(Integer id) {
        return pcMapper.selectById(id);
    }



    @Transactional
    @Override
    public void updateStatus(CustomerPayment customerPayment){

//        AtomicReference<Boolean> isAudit = new AtomicReference<>(false);
//        if (planCollect1.getWorkflowJsonList() != null && planCollect1.getWorkflowJsonList().size() != 0) {
//            planCollect1.getWorkflowJsonList().forEach(workflowJson -> {
//                if (workflowJson.getType() == 1) {
//                    isAudit.set(true);
//                }
//            });
//        }
        Date date = null;
        //自动生成编号
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        if (customerPayment.getCreateTime() != null) {
            date = customerPayment.getCreateTime();
        } else {
            date = new Date();
        }
        String code = "HK-" + sdf.format(date);
        String maxCode =  customerPaymentMapper.maxRoundInoutNumber(code);
        String newCode = null;
        if (StrUtil.isEmpty(maxCode)){
            newCode = code + "001";
        }
        else {
            String getMaxCode = maxCode.substring(11, 14);
            newCode = code + DateNumUtils.getNum(getMaxCode);
        }        customerPayment.setCreateTime(DateUtil.date());
        customerPayment.setRepaymentNum(newCode);
        String paymentName = null;
        if (customerPayment.getPaymentType() == 1){
            List<Integer> collect = customerPayment.getPlanCollects()
                    .stream()
                    .map(PlanCollect::getContractId)
                    .collect(Collectors.toList());
            List<String> contractsName = contractMapper
                    .selectList(new QueryWrapper<Contract>()
                            .lambda()
                            .in(Contract::getId, collect))
                    .stream().map(Contract::getName)
                    .collect(Collectors.toList());
            paymentName = StrUtil.join(",",contractsName);
        }
        if(customerPayment.getPaymentType() == 3){
            List<Integer> customerId = customerPayment.getPlanCollects().stream().distinct().map(PlanCollect::getCustomerId).collect(Collectors.toList());
            Customer customer = customerMapper.selectById(customerId.get(0));
            paymentName = customer.getCustomerName();
        }


        customerPayment.setStatus(1);
        customerPayment.setPaymentName(paymentName.concat("-的收款"));
        customerPaymentMapper.insert(customerPayment);

        AtomicReference<Double> customerMoney = new AtomicReference<>(Double.valueOf(0));
        customerPayment.getPlanCollects().forEach(planCollect -> {
            //判断在审金额 + 本次回款金额+西小于应收账单金额
            Double money = Double.valueOf(0);
            //查询单条的在审金额
            List<PaymentContract> paymentContracts = paymentContractMapper.selectMoneyByContractId(planCollect.getId(),planCollect.getContractId());
            if(paymentContracts!=null &&paymentContracts.size()!=0) {
                money = paymentContracts.stream().map(PaymentContract::getMoney).reduce((a,b)-> a+b ).get();
            }
            if(money + planCollect.getMoney() > planCollect.getPlanMoney()){
                //超出当前计划金额，直接报错
                throw new CustomException(ResultCode.EXCEED_PLAN_MONEY);
            }
            PaymentContract paymentContract = new PaymentContract();
            //判断 当前 应收单 是否有应收金额
//            if (planCollect.getActualPlanMoney() == null || planCollect.getActualPlanMoney() == 0 ){
//                paymentContract.setBillId(customerPayment.getBillId());
//            }
            paymentContract.setPlanId(planCollect.getId());
            paymentContract.setContractId(planCollect.getContractId());
            paymentContract.setPaymentId(customerPayment.getId());
            paymentContract.setBalancingAccounts(planCollect.getBalancingAccounts());
            paymentContract.setMoney(planCollect.getMoney());
            paymentContract.setCreateTime(DateUtil.date());
            paymentContract.setRemark(planCollect.getRemark());
            customerMoney.updateAndGet(v -> v + planCollect.getMoney());
            if(customerPayment.getStatus() == 1 && customerPayment.getPaymentType()== 3){
                paymentContract.setBillId(customerPayment.getBillId());
            }
            paymentContractMapper.insert(paymentContract);

//            if(paymentContract.getBalancingAccounts() == 1){
//                // 检测当条在审金额
//                Double aDouble   = customerPaymentService.selectMoneyByPlanId(planCollect.getId(), planCollect.getContractId());
//                if (aDouble != 0 || aDouble != null){
//                    throw new CustomException(ResultCode.AUDIT_MONEY_IS_DATA);
//                }
//            }
         });

        //修改总金额
         customerPayment.setMoney(customerMoney.get());
         customerPaymentMapper.updateById(customerPayment);

//        if (!isAudit.get()) {
//            generateList(contract,customerPayment,isAudit.get() ? false : true);
//        }

        if(customerPayment.getStatus() == 1 && customerPayment.getPaymentType()==1){
            generateList(customerPayment,true);
        } else if (customerPayment.getStatus() == 1 && customerPayment.getPaymentType()== 3) {
            billService.updateBillCustomer(customerPayment);
        }
//
//        AddPageData addPageData = new AddPageData();
//        addPageData.setAdminId(customerPayment.getAdminId());
//        addPageData.setCorrelationId(customerPayment.getId());
//        addPageData.setWorkflowJson(customerPayment.getWorkflowJsonList());
//        addPageData.setStreamType(5);
//        addPageData.setTitle(customerPayment.getPaymentName());
//        addPageData.setExempt(customerPayment.getExempt());
//        return addPageData;
    }


    @Override
    public void generateList(CustomerPayment customerPayment1,Boolean updateStatus){
        CustomerPayment customerPayment = customerPaymentService.detailById(customerPayment1.getId());
        customerPayment.getPaymentContracts().forEach(paymentContract -> {
            PlanCollect planCollect = pcMapper.selectById(paymentContract.getPlanId());
            Contract contract = contractMapper.selectById(planCollect.getContractId());
            if(planCollect != null){
                if(updateStatus){
                    Double actualPlanMoney = planCollect.getActualPlanMoney() ==null ?0.00:planCollect.getActualPlanMoney();
                    planCollect.setActualPlanMoney(paymentContract.getMoney() + actualPlanMoney);
                    planCollect.setUpdateTime(DateUtil.date());
                    Double countMoney = planCollect.getPlanMoney() - actualPlanMoney;
                    if(paymentContract.getBalancingAccounts()==0){
                        // 比较当前实缴金额是否等于当前计划金额减去回款的，是则更改主表状态，不是单子还未收款完成
                        if(countMoney.equals(customerPayment.getMoney())){
                            planCollect.setPlanStatus(1);
                            generateDetailList(contract);
                        }
                    } else {
                        // 抹零平账,回款完成
                        planCollect.setBalancingMoney(countMoney-customerPayment.getMoney());
                        planCollect.setPlanStatus(1);
                        generateDetailList(contract);
                    }
                    pcMapper.updateById(planCollect);
                } else {
                    generateDetailList(contract);
                }
            }
        });


    }

    private void generateDetailList(Contract contract){
        //判断计划管理是否有多天数据，如果有数据则不生产单
        QueryWrapper<PlanCollect> planCollectQueryWrapper = new QueryWrapper<>();
        planCollectQueryWrapper.lambda().eq(PlanCollect::getContractId,contract.getId())
                .eq(PlanCollect::getPlanPayType,1).eq(PlanCollect::getPlanStatus,1);
        List<PlanCollect> planCollect = pcMapper.selectList(planCollectQueryWrapper);
        if(contract.getPaymentMethod() == 1){
            QueryWrapper<AdminDepartment> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().in(AdminDepartment::getAdminId,contract.getPayee(),contract.getProductionPerson());
            List<AdminDepartment> adminDepartment = adminDepartmentMapper.selectList(queryWrapper);
            Integer productionPerson = adminDepartment.stream().filter(e->e.getAdminId().equals(contract.getProductionPerson())).findFirst().get().getDepartmentId();
            Integer payee = adminDepartment.stream().filter(e->e.getAdminId()==contract.getPayee()).findFirst().get().getDepartmentId();
            //生成生产单，查询合同是否生成过生产单，是则跳过生产，不是则生成
            if(planCollect.size()!=0 || planCollect!=null){
                // 到付的话，则直接生成单子,并且不是建模的情况下
                if(contract.getCombination() == 2 && contract.getModeling() == 0){
                    Produce produce = new Produce();
                    produce.setCreateTime(DateUtil.date());
                    produce.setName(contract.getName().concat("-生产单"));
                    produce.setContractId(contract.getId());
                    produce.setAdminId(contract.getAdminId());
                    produce.setDepartmentId(productionPerson);
                    produce.setResponsibleId(contract.getProductionPerson());
                    produce.setStatus(1);
                    produceMapper.insert(produce);
                    //生产生产单关联表
                    QueryWrapper<QuotesProducts> productsQueryWrapper = new QueryWrapper<>();
                    productsQueryWrapper.lambda().eq(QuotesProducts::getQuotesId,contract.getQuotesId());
                    List<QuotesProducts> quotesProducts = quotesProductsMapper.selectList(productsQueryWrapper);
                    // 插入报价单子到生产单中
                    if(quotesProducts==null&&quotesProducts.size()==0){
                        throw new CustomException(ResultCode.PARAM_IS_BLANK);
                    }
                    quotesProducts.forEach(quotesProducts3 -> {
                        ProduceProducts produceProducts = new ProduceProducts();
                        produceProducts.setProduceId(produce.getId());
                        produceProducts.setQuotesProductId(quotesProducts3.getProductsId());
                        produceProducts.setNum(quotesProducts3.getNum());
                        produceProducts.setProduceStatus(0);
                        produceProductsMapper.insert(produceProducts);
                    });
                }
                //创建应收款
                if(contract.getModeling() == 1 && contract.getCombination() == 2){
                    PlanCollect planCollect2 = new PlanCollect();
                    planCollect2.setContractId(contract.getId());
                    planCollect2.setCreateTime(DateUtil.date());
                    planCollect2.setAdminId(contract.getPayee());
                    planCollect2.setActualPlanMoney(0.00);
                    planCollect2.setPlanMoney(contract.getMoney()-contract.getPrepaymentMoney());
                    planCollect2.setDepartmentId(payee);
                    planCollect2.setPlanTime(DateUtil.offsetDay(DateUtil.date(),2));
                    pcMapper.insert(planCollect2);
                }
            }
            // 剩余金额计划回款, 约定时间
            if(contract.getCombination() == 3){
                PlanCollect planCollect2 = new PlanCollect();
                planCollect2.setContractId(contract.getId());
                planCollect2.setCreateTime(DateUtil.date());
                planCollect2.setAdminId(contract.getPayee());
                planCollect2.setActualPlanMoney(0.00);
                planCollect2.setPlanMoney(contract.getMoney()-contract.getPrepaymentMoney());
                planCollect2.setDepartmentId(payee);
                planCollect2.setPlanTime(contract.getAgreeTime());
                pcMapper.insert(planCollect2);
            }
        }
    }

    @Override
    public Map<String, Object> financeStatistics() {
        Map<String, Object> map = new HashMap<>();

        //实收 年
        Double customerPaymentYearMoney = customerPaymentMapper.selectYearActualMoney() == null ? 0 : customerPaymentMapper.selectYearActualMoney();
        map.put("customerPaymentYearMoney", customerPaymentYearMoney);
        //实收 月
        Double customerPaymentMonthMoney = customerPaymentMapper.selectMonthActualMoney() == null ? 0 : customerPaymentMapper.selectMonthActualMoney();
        map.put("customerPaymentMonthMoney", customerPaymentMonthMoney);

        //应收 年
        Double planYearMoney = pcMapper.selectYearPlanMoney() == null ? 0 : pcMapper.selectYearPlanMoney();
        map.put("planYearMoney", planYearMoney);
        //应收 月
        Double planMonthMoney = pcMapper.selectMonthPlanMoney() == null ? 0 : pcMapper.selectMonthPlanMoney();
        map.put("planMonthMoney", planMonthMoney);

        //付款 年
        Double paymentYearMoney = paymentMapper.selectYearPaymentMoney() == null ? 0 : paymentMapper.selectYearPaymentMoney();
        map.put("paymentYearMoney", paymentYearMoney);
        //付款 月
        Double paymentMonthMoney = paymentMapper.selectMonthPaymentMoney() == null ? 0 : paymentMapper.selectMonthPaymentMoney();
        map.put("paymentMonthMoney", paymentMonthMoney);

        //报销 年
        Double reimburseYearMoney = reimbursementMapper.selectYearReimburseMoney() == null ? 0 : reimbursementMapper.selectYearReimburseMoney();
        map.put("reimburseYearMoney" , reimburseYearMoney);
        //报销 月
        Double reimburseMonthMoney = reimbursementMapper.selectMonthReimburseMoney() == null ? 0 : reimbursementMapper.selectMonthReimburseMoney();
        map.put("reimburseMonthMoney", reimburseMonthMoney);

        //借款 年
        Double loanYearMoney = loanMapper.selectYearLoanMoney() == null ? 0 : loanMapper.selectYearLoanMoney() ;
        map.put("loanYearMoney", loanYearMoney);
        //借款 月
        Double loanMonthMoney = loanMapper.selectMonthLoanMoney() == null ? 0 : loanMapper.selectMonthLoanMoney();
        map.put("loanMonthMoney", loanMonthMoney);
        return map;
    }


    @Override
    public void updateData(){
        List<PlanCollect> planCollects = pcMapper.selectList(null);
        planCollects.forEach(planCollect -> {
            Contract contract = contractMapper.selectById(planCollect.getContractId());
            planCollect.setCustomerId(contract.getCustomerId());
            planCollect.setUpdateTime(DateUtil.date());
            pcMapper.updateById(planCollect);
        });
    }

    @Override
    public Map<String,Object> moneyForYear(String year) {
        if (StrUtil.isBlank(year)){
            year = DateUtil.format(DateUtil.date(),"yyyy");
        }
        Map<String, Object> map = new HashMap<>();
        Double planMoney = pcMapper.selectMoneyForYear(year);
        Double customerPaymentMoney = customerPaymentMapper.selectMoneyForYear(year);
        Double reimburseMoney = reimbursementMapper.selectMoneyForYear(year);
        Double loanMoney = loanMapper.selectMoneyForYear(year);
        Double paymentMoney = paymentMapper.selectMoneyForYear(year);
        map.put("planMoney",planMoney);
        map.put("customerPaymentMoney", customerPaymentMoney);
        map.put("reimburseMoney",reimburseMoney);
        map.put("loanMoney",loanMoney);
        map.put("paymentMoney",paymentMoney);
        return map;
    }


    @Override
    public Map<String,Object> listStatistics(){
        Map<String,Object> data = pcMapper.selectListStatistics();
        return data;
    }

    @Override
    public LinkedHashMap<String, Object> planMonthlyStatistics(String time) {
        if (StrUtil.isBlank(time)){
            time = DateUtil.format(DateUtil.date(),"yyyy");
        }
        return pcMapper.planMonthlyStatistics(time);
    }

    @Override
    public Map<String, Object> totalPercentage(String time) {
        if (StrUtil.isBlank(time)){
            time = DateUtil.format(DateUtil.date(),"yyyy");
        }

        NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置精确到小数点后2位
        numberFormat.setMaximumFractionDigits(1);
        //实收年
        Double customerPaymentMoney = customerPaymentMapper.selectMoneyForYear(time)==null ? 0 : customerPaymentMapper.selectMoneyForYear(time);
        //应收年
        Double planMoney = pcMapper.selectTotalPlanMoney(time) == null ? 0 : pcMapper.selectTotalPlanMoney(time);

        //当前月的实收
        Double monthMoney = customerPaymentMapper.selectMonthActualMoney() == null ? 0 : customerPaymentMapper.selectMonthActualMoney();
        //当前月的应收
        Double pcMonthMoney = pcMapper.selectMonthPlanMoney() == null ? 0 : pcMapper.selectMonthPlanMoney();
        Double customerPaymentPercentage = (monthMoney / customerPaymentMoney) * 100;
        Double planMoneyPercentage = (pcMonthMoney/planMoney) * 100 ;
        Map<String, Object> map = new HashMap<>();
        map.put("customerPaymentPercentage", numberFormat.format(customerPaymentPercentage));
        map.put("planMoneyPercentage", numberFormat.format(planMoneyPercentage));
        return map;
    }

    @Override
    public List<PlanCustomerPayment> planCustomerPaymentStatist(String time) {
        if (StrUtil.isBlank(time)){
            time = DateUtil.format(DateUtil.date(),"yyyy");
        }
        LinkedHashMap<String, Object> objectMap = pcMapper.planMonthlyStatistics(time);
        LinkedHashMap<String, Object> objectMap1 = customerPaymentMapper.customerPaymentMonthlyStatistics(time);
        List<PlanCustomerPayment> lists = new ArrayList<>();
        for (String monthKey : objectMap.keySet()) {
            PlanCustomerPayment planCustomerPayment = new PlanCustomerPayment();
            planCustomerPayment.setMothName(monthKey);
            planCustomerPayment.setPlanMonthMoney(objectMap.get(monthKey));
            planCustomerPayment.setCustomerPaymentMonthMoney(objectMap1.get(monthKey));
            lists.add(planCustomerPayment);
        } 
        return lists;
    }

    @Override
    public Map<String, Object> financeTotal(String time) {
        if (StrUtil.isBlank(time)){
            time = DateUtil.format(DateUtil.date(),"yyyy");
        }
        Map<String, Object> map = new HashMap<>();
        //实收 年
        Double customerPaymentYearMoney = customerPaymentMapper.selectMoneyForYear(time) == null ? 0 : customerPaymentMapper.selectMoneyForYear(time);
        map.put("customerPaymentYearMoney", customerPaymentYearMoney);
        //应收 年
        Double planYearMoney = pcMapper.selectMoneyForYear(time) == null ? 0 : pcMapper.selectMoneyForYear(time);
        map.put("planYearMoney", planYearMoney);
        //付款 年
        Double paymentYearMoney = paymentMapper.selectMoneyForYear(time) == null ? 0 : paymentMapper.selectMoneyForYear(time);
        map.put("paymentYearMoney", paymentYearMoney);
        //报销 年
        Double reimburseYearMoney = reimbursementMapper.selectMoneyForYear(time) == null ? 0 : reimbursementMapper.selectMoneyForYear(time);
        map.put("reimburseYearMoney" , reimburseYearMoney);

        //借款 年
        Double loanYearMoney = loanMapper.selectMoneyForYear(time) == null ? 0 : loanMapper.selectMoneyForYear(time) ;
        map.put("loanYearMoney", loanYearMoney);
        return map;
    }
}
